package com.cm.projectx.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.text.StrPool;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cm.projectx.entity.MainJcdglVoyfpoul;
import com.cm.projectx.entity.MainWjxxbsOfmwexaz;
import com.cm.projectx.entity.SubEditabletable1756697848650Fdmikchn;
import com.cm.projectx.mapper.SubEditabletable1756697848650FdmikchnMapper;
import com.cm.projectx.service.IMainJcdglVoyfpoulService;
import com.cm.projectx.service.IMainWjxxbsOfmwexazService;
import com.cm.projectx.service.ISubEditabletable1756697848650FdmikchnService;
import com.cm.projectx.util.PoiHelper;
import com.cm.projectx.vo.PriceSearchVo;
import lombok.RequiredArgsConstructor;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Array;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Service
@RequiredArgsConstructor
public class SubEditabletable1756697848650FdmikchnServiceImpl extends ServiceImpl<SubEditabletable1756697848650FdmikchnMapper, SubEditabletable1756697848650Fdmikchn> implements ISubEditabletable1756697848650FdmikchnService {
    private final IMainWjxxbsOfmwexazService mainWjxxbsOfmwexazService;
    private final IMainJcdglVoyfpoulService mainJcdglVoyfpoulService;

    @Value("${spring.file.template.path}")
    private String templateFilePath;
    private final List<String> NUMBER_STR = Arrays.asList("一、", "二、", "三、", "四、", "五、", "六、", "七、", "八、", "九、", "十、", "十一、", "十二、", "十三、", "十四、", "十五、", "十六、", "十七、", "十八、", "十九、");

    private static Map<String, String> SHEET_FIELD_CONFIG = new HashMap() {{
        put("no", "0");
        put("name", "1");
        put("kind", "2");
        put("unit", "3");
        put("avgSalePrice", "4");
        put("avgMarketPrice", "5");
        put("boxingSalePrice", "6");
        put("boxingMarketPrice", "7");
        put("huiminSalePrice", "8");
        put("huiminMarketPrice", "9");
        put("zhanhuaSalePrice", "10");
        put("zhanhuaMarketPrice", "11");
        put("binchengSalePrice", "12");
        put("binchengMarketPrice", "13");
        put("yangxinSalePrice", "14");
        put("yangxinMarketPrice", "15");
    }};

    @Override
    public List<Map<String, Object>> selectPage(PriceSearchVo priceSearchVo) {
        //获取区县列表
        List<MainJcdglVoyfpoul> voyfpoulList = mainJcdglVoyfpoulService.list();
        List<String> districtList = voyfpoulList.stream()
                .map(MainJcdglVoyfpoul::getInput1756457125178)
                .collect(Collectors.toList());


        //根据价格类型和时间获取抓表列表
        HashSet<String> districtSet = new HashSet<>();
        List<MainWjxxbsOfmwexaz> ofmwexazs = mainWjxxbsOfmwexazService.list(Wrappers.<MainWjxxbsOfmwexaz>lambdaQuery()
                        .eq(MainWjxxbsOfmwexaz::getSelect1756456950574, priceSearchVo.getPriceType())
                        .like(MainWjxxbsOfmwexaz::getDatePicker1757414426057, priceSearchVo.getDatePicker())
                        .in(MainWjxxbsOfmwexaz::getInput1757552047326, districtList))
                .stream()
                .filter(d -> districtSet.add(d.getInput1757552047326()))
                .collect(Collectors.toList());
        List<String> parentIds = ofmwexazs.stream().map(MainWjxxbsOfmwexaz::getId).collect(Collectors.toList());
        if(CollUtil.isEmpty(parentIds)) {
            parentIds = Collections.singletonList("-1");
        }

        //获取各区县的价格数据
        List<SubEditabletable1756697848650Fdmikchn> basePriceData = list(Wrappers.<SubEditabletable1756697848650Fdmikchn>lambdaQuery()
                .in(SubEditabletable1756697848650Fdmikchn::getParentId, parentIds)
                .eq(StrUtil.isNotEmpty(priceSearchVo.getItemType()), SubEditabletable1756697848650Fdmikchn::getInput1756697848650, priceSearchVo.getItemType())
                .eq(StrUtil.isNotEmpty(priceSearchVo.getItemName()), SubEditabletable1756697848650Fdmikchn::getProperty1757655874378, priceSearchVo.getItemName()));
        return generateReportData(ofmwexazs, basePriceData);
    }

    @Override
    public Map<String, Object> exportExcel(PriceSearchVo priceSearchVo) {
        //方法返回excel文件信息
        Map<String, Object> exportFileInfo = new HashMap<>(4);

        //加载模板文件
        InputStream stream = FileUtil.getInputStream(templateFilePath + "priceMonitor.xlsx");
        XSSFWorkbook workbook;
        try {
            List<Map<String, Object>> data = selectPage(priceSearchVo);

            workbook = new XSSFWorkbook(stream);

            //获取sheet并设置表头信息
            XSSFSheet sheet = workbook.getSheet("Sheet1");
            XSSFRow titleRow = sheet.getRow(0);
            XSSFCell titleCell = titleRow.getCell(0);
            String newTitle = titleCell.getStringCellValue() + "(" + priceSearchVo.getDatePicker() + ")";
            titleCell.setCellValue(newTitle);
            XSSFRow dateRow = sheet.getRow(1);
            XSSFCell dateCell = dateRow.getCell(0);
            dateCell.setCellValue(priceSearchVo.getDatePicker());

            //遍历列表给excel赋值
            for (int i = 0; i < data.size(); i++) {
                setRowFromEntityObj(data.get(i), sheet);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        exportFileInfo.put("excel_file_name", "居民生活消费（食）品零售价格监测报表(县、市、区)(" + priceSearchVo.getDatePicker() + ")-" + priceSearchVo.getPriceType() + ".xlsx");
        exportFileInfo.put("excel_file_content", workbook);
        return exportFileInfo;
    }

    @Override
    public List<String> getDateList(PriceSearchVo priceSearchVo) {
        List<MainWjxxbsOfmwexaz> ofmwexazs = mainWjxxbsOfmwexazService.list(Wrappers.<MainWjxxbsOfmwexaz>lambdaQuery()
                        .eq(MainWjxxbsOfmwexaz::getSelect1756456950574, priceSearchVo.getPriceType()));
        return ofmwexazs.stream()
                .map(m -> DateUtil.format(m.getDatePicker1757414426057(), "yyyy-MM-dd"))
                .distinct().collect(Collectors.toList());
    }

    /**
     * 表格Row赋值
     *
     * @param recordBean
     * @param sheet
     */
    private void setRowFromEntityObj(Object recordBean,
                                     XSSFSheet sheet) {
        XSSFRow row = PoiHelper.getNextXssfRow(sheet, 4);

        //字段对应关系（此处导出当审核菜单时所有字段的值都要导出）
        for (Map.Entry<String, String> fieldEntry : SHEET_FIELD_CONFIG.entrySet()) {
            String fieldName = fieldEntry.getKey();

            int columnNumber = Integer.parseInt(fieldEntry.getValue());
            XSSFCell cell = row.getCell(columnNumber);
            if (Objects.isNull(cell)) {
                log.error("获取列号：" + (columnNumber + 1) + " 单元格为空，检查模板文件和字段配置是否正确！！！");
            }

            Object value = BeanUtil.getFieldValue(recordBean, fieldName);

            if (value != null) {
                PoiHelper.setValueToCellV2(cell, value);
            }
        }
    }

    /**
     * 根据各区县各商品价格信息生成所需报表信息
     * @param basePriceData
     * @return
     */
    private List<Map<String, Object>> generateReportData(List<MainWjxxbsOfmwexaz> ofmwexazs, List<SubEditabletable1756697848650Fdmikchn> basePriceData) {
        Map<String, String> districtMapping = ofmwexazs.stream().collect(
                Collectors.toMap(MainWjxxbsOfmwexaz::getInput1757552047326, MainWjxxbsOfmwexaz::getId, (a, b) -> b));

        ArrayList<Map<String, Object>> result = new ArrayList<>();
        if (CollUtil.isEmpty(basePriceData)) {
            return result;
        }

        Map<String, List<SubEditabletable1756697848650Fdmikchn>> districtPriceData = basePriceData.stream().collect(Collectors.groupingBy(SubEditabletable1756697848650Fdmikchn::getParentId));

        List<String> productInfoList = basePriceData.stream().map(
                s -> StrUtil.join(StrPool.AT,s.getInput1756697848650(),s.getProperty1757655874378(),s.getProperty1756698675664()))
                .distinct()
                .sorted().collect(Collectors.toList());

        String boxingId = districtMapping.get("博兴县农贸采价点");
        Map<String, SubEditabletable1756697848650Fdmikchn> boxingProductMapping = getProductMapping(districtPriceData, boxingId);
        String huimingId = districtMapping.get("惠民县农贸采价点");
        Map<String, SubEditabletable1756697848650Fdmikchn> huimingProductMapping = getProductMapping(districtPriceData, huimingId);


        String zhanhuaId = districtMapping.get("沾化区农贸采价点");
        Map<String, SubEditabletable1756697848650Fdmikchn> zhanhuaProductMapping = getProductMapping(districtPriceData, zhanhuaId);

        String binchengId = districtMapping.get("滨城区农贸采价点");
        Map<String, SubEditabletable1756697848650Fdmikchn> binchengProductMapping = getProductMapping(districtPriceData, binchengId);

        String yangxinId = districtMapping.get("阳信县农贸采价点");
        Map<String, SubEditabletable1756697848650Fdmikchn> yangxinProductMapping = getProductMapping(districtPriceData, yangxinId);

        String type = "";
        int number = 0;

        for (String item : productInfoList) {
            HashMap<String, Object> record = new HashMap<>();
            List<String> productInfo = StrUtil.split(item, StrPool.AT);

            if(!StrUtil.equals(type, productInfo.get(0))) {
                HashMap<String, Object> typeRecord = new HashMap<>();
                typeRecord.put("name", NUMBER_STR.get(number) + productInfo.get(0));
                result.add(typeRecord);
                type = productInfo.get(0);
            }
            //序号
            record.put("no", ++number);
            //名称
            record.put("name", productInfo.get(1));
            //规格
            record.put("kind", productInfo.get(2));

            String unit = "";
            SubEditabletable1756697848650Fdmikchn priceInfoObj = getProductPriceObj(boxingProductMapping, productInfo.get(1), productInfo.get(2));
            if (StrUtil.isNotEmpty(priceInfoObj.getProperty1756698692357())) {
                unit = priceInfoObj.getProperty1756698692357();
            }
            Double boxingSalePrice = priceInfoObj.getProperty1756698796775();
            Double boxingMarketPrice = priceInfoObj.getProperty1757408028781();

            record.put("boxingSalePrice", boxingSalePrice);
            record.put("boxingMarketPrice", boxingMarketPrice);

            priceInfoObj = getProductPriceObj(huimingProductMapping, productInfo.get(1), productInfo.get(2));
            if (StrUtil.isNotEmpty(priceInfoObj.getProperty1756698692357())) {
                unit = priceInfoObj.getProperty1756698692357();
            }
            Double huiminSalePrice = priceInfoObj.getProperty1756698796775();
            Double huiminMarketPrice = priceInfoObj.getProperty1757408028781();
            record.put("huiminSalePrice", huiminSalePrice);
            record.put("huiminMarketPrice", huiminMarketPrice);

            priceInfoObj = getProductPriceObj(zhanhuaProductMapping, productInfo.get(1), productInfo.get(2));
            if (StrUtil.isNotEmpty(priceInfoObj.getProperty1756698692357())) {
                unit = priceInfoObj.getProperty1756698692357();
            }
            Double zhanhuaSalePrice = priceInfoObj.getProperty1756698796775();
            Double zhanhuaMarketPrice = priceInfoObj.getProperty1757408028781();
            record.put("zhanhuaSalePrice", zhanhuaSalePrice);
            record.put("zhanhuaMarketPrice", zhanhuaMarketPrice);

            priceInfoObj = getProductPriceObj(binchengProductMapping, productInfo.get(1), productInfo.get(2));
            if (StrUtil.isNotEmpty(priceInfoObj.getProperty1756698692357())) {
                unit = priceInfoObj.getProperty1756698692357();
            }
            Double binchengSalePrice = priceInfoObj.getProperty1756698796775();
            Double binchengMarketPrice = priceInfoObj.getProperty1757408028781();
            record.put("binchengSalePrice", binchengSalePrice);
            record.put("binchengMarketPrice", binchengMarketPrice);

            priceInfoObj = getProductPriceObj(yangxinProductMapping, productInfo.get(1), productInfo.get(2));
            if (StrUtil.isNotEmpty(priceInfoObj.getProperty1756698692357())) {
                unit = priceInfoObj.getProperty1756698692357();
            }
            Double yangxinSalePrice = priceInfoObj.getProperty1756698796775();
            Double yangxinMarketPrice = priceInfoObj.getProperty1757408028781();
            record.put("yangxinSalePrice", yangxinSalePrice);
            record.put("yangxinMarketPrice", yangxinMarketPrice);

            //计量单位
            record.put("unit", unit);

            Double avgSalePrice = Stream.of(boxingSalePrice, huiminSalePrice, zhanhuaSalePrice, binchengSalePrice, yangxinSalePrice).filter(Objects::nonNull).mapToDouble(d -> d).average().orElse(0d);
            Double avgMarketPrice = Stream.of(boxingMarketPrice, huiminMarketPrice, zhanhuaMarketPrice, binchengMarketPrice, yangxinMarketPrice).filter(Objects::nonNull).mapToDouble(d -> d).average().orElse(0d);

            record.put("avgSalePrice", String.format("%.2f", avgSalePrice));
            record.put("avgMarketPrice", String.format("%.2f", avgMarketPrice));
            result.add(record);
        }

        return result;
    }

    private Map<String, SubEditabletable1756697848650Fdmikchn> getProductMapping(Map<String, List<SubEditabletable1756697848650Fdmikchn>> districtPriceData, String boxingId) {
        List<SubEditabletable1756697848650Fdmikchn> boxingData = districtPriceData.get(boxingId);
        if (boxingData == null) {
            return null;
        }
        Map<String, SubEditabletable1756697848650Fdmikchn> boxingProductMapping = boxingData.stream()
                .collect(
                        Collectors.toMap(
                                s -> StrUtil.join(StrPool.AT, s.getProperty1757655874378(), s.getProperty1756698675664()),
                                Function.identity()
                        )
                );
        return boxingProductMapping;
    }

    private SubEditabletable1756697848650Fdmikchn getProductPriceObj(Map<String, SubEditabletable1756697848650Fdmikchn> productMapping, String name, String kind) {
        SubEditabletable1756697848650Fdmikchn result = new SubEditabletable1756697848650Fdmikchn();
        if (productMapping != null) {
            SubEditabletable1756697848650Fdmikchn curInfo = productMapping.get(name + StrPool.AT + kind);
            if (Objects.nonNull(curInfo)) {
                result = curInfo;
            }
        }

        return result;
    }

}
